#ifndef GAMEENGINE_CORE_MEMORY_OWNED_PTR_H
#define GAMEENGINE_CORE_MEMORY_OWNED_PTR_H

#include <GameEngine/Core/core_settings.h>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif


//========================================================


//! Handles pointers that can own their memory
/*!
 *  If the owned pointer owns the memory associated to the pointer, it automatically
 *  deletes it when the last owned pointer if destroyed.
 *
 *  This structure uses a doubly linked list to related owned pointers in order to
 *  "remember" which other owned pointers also point to the data. When the owned pointer
 *  destructor is called, if the owned pointer about to be destroyed was the owner of the
 *  memory, it tries to give ownership to one other pointer using the same data. If there
 *  is no such pointer, the memory is actually released.
 *
 *  Because of the doubly linked list structure, owned pointers are quite costly in
 *  memory and should be used sparingly. One of the big strenghs of this class is the
 *  ability to copy owned pointers, using either the copy constructor or the assignment
 *  operator, without invalidating the copied owned pointer. If there is no need to have
 *  such a mechanism, the use of the std::auto_ptr class is preferable, since it is much
 *  lighter in memory.
 */
template <class T>
class OwnedPtr {

public:
	OwnedPtr();
	OwnedPtr(T* ptr, bool owner=true);
	OwnedPtr(const OwnedPtr& rhs);
	virtual ~OwnedPtr();
	OwnedPtr& operator=(const OwnedPtr& rhs);

	bool set_ptr(T* ptr, bool owner=true);

	T* ptr() const;
	T& operator*();
	T* operator->();
	T& operator[](const int location);

private:
	//! Pointer to the data
	T* ptr_;
	//! Flag that determines whether the owned pointer owns the memory for the data
	bool owner_;

	//! Pointer to the owned pointer before this one (double linked list structure)
	mutable const OwnedPtr* before_;
	//! Pointer to the owned pointer after this one (double linked list structure)
	mutable const OwnedPtr* after_;
};


//========================================================

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#include <GameEngine/Core/Memory/owned_ptr.hpp>

#endif
